/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.dictionary.impl.typed;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.je.common.base.DynaBean;
import com.je.common.base.constants.ConstantVars;
import com.je.common.base.constants.dd.DDType;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.mapper.query.Condition;
import com.je.common.base.mapper.query.Query;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.QueryBuilderService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.util.StringUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.cache.dd.DicInfoCache;
import com.je.meta.service.dictionary.AbstractMetaDictionaryTreeServiceImpl;
import com.je.meta.service.dictionary.MetaDictionaryTreeService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

@Service("dynaTreeDictionaryTreeService")
public class DynaTreeDictionaryTreeServiceImpl extends AbstractMetaDictionaryTreeServiceImpl implements MetaDictionaryTreeService {

    private static final Logger logger = LoggerFactory.getLogger(DynaTreeDictionaryTreeServiceImpl.class);


    List<String> needFilterByProduct = Lists.newArrayList(
            "JE_CORE_MENU"
    );

    @Autowired
    private MetaService metaService;
    @Autowired
    private DicInfoCache dicInfoCache;
    @Autowired
    private BeanService metaBeanService;
    @Autowired
    private QueryBuilderService queryBuilder;

    @Override
    public List<JSONTreeNode> loadAsynTree(JSONObject obj,String product, boolean en, boolean onlyItem) {
        //构建返回结果
        List<JSONTreeNode> array = new ArrayList<>();

        //根节点ID,默认为ROOT
        String rootId = obj.getString("rootId");
        if (StringUtil.isEmpty(rootId)) {
            rootId = ConstantVars.TREE_ROOT;
        }

        //字典编码
        String ddCode = obj.getString("ddCode");
        //字典名称，非必需字段
        String ddName = obj.getString("ddName");
        //字典标识，非必需字段 创建根节点对象ID使用,一次加载多个字典时使用
        String nodeInfo = obj.getString("nodeInfo");
        //默认为1  是否从根节点查找数据
        String isRoot = obj.containsKey("isRoot") ? obj.getString("isRoot") : "1";

        //构建根节点
        JSONTreeNode emptyRoot = new JSONTreeNode();
        emptyRoot.setText(ddName);
        emptyRoot.setParent("ROOT");
        emptyRoot.setId("ROOT_" + nodeInfo);
        emptyRoot.setNodeInfo(nodeInfo);

        //查找字典主表记录
        DynaBean dictionary = dicInfoCache.getCacheValue(ddCode);
        if (dictionary == null) {
            dictionary = metaService.selectOne("JE_CORE_DICTIONARY", ConditionsWrapper.builder().eq("DICTIONARY_DDCODE", ddCode));
        }
        if (dictionary == null) {
            array.add(emptyRoot);
            throw new PlatformException("未找到数据字典：" + ddCode + "!", PlatformExceptionEnum.JE_CORE_DIC_UNKOWN_ERROR, new Object[]{ddCode});
        }

        //字典类型，本方法支持[外部树形字典，列表字典，树形字典]
        String ddType = dictionary.getStr("DICTIONARY_DDTYPE");
        //字典对应表名，普通列表与普通树形字典此值为空
        String tableName = "JE_CORE_DICTIONARYITEM";

        if (!DDType.DYNA_TREE.equalsIgnoreCase(ddType)) {
            throw new PlatformException("错误的字典类型：" + ddType + "!", PlatformExceptionEnum.JE_CORE_DIC_UNKOWN_ERROR, new Object[]{ddCode});
        }

        //前端sql条件转换
        Query query;
        if (StringUtils.isNotBlank(obj.getString("j_query"))) {
            query = Query.build(obj.getString("j_query"));
        } else {
            query = new Query();
        }

        if(needFilterByProduct.contains(ddCode)){
            commonService.buildProductQuery(query);
        }

        // 租户ID
        String adminPermSql = "";

        //条件构建器 //添加 adminPermSql
        ConditionsWrapper wrapper = query.buildWrapper();
        //获取Admin权限sql
        String queryTableCode = obj.getString("queryTableCode");
        if (StringUtils.isNotBlank(queryTableCode)) {
            adminPermSql = getQuerySql(queryTableCode);
            if (StringUtils.isNotBlank(adminPermSql)) {
                final String sql = adminPermSql;
                wrapper.and(i -> i.apply(queryBuilder.trimSql(sql)));
            }
        }

        //构建查询字典ID关联
        wrapper.eq("DICTIONARYITEM_DICTIONARY_ID", dictionary.getStr("JE_CORE_DICTIONARY_ID"));
        //查找根节点
        if ("1".equals(isRoot)) {
            if (ConstantVars.TREE_ROOT.equals(rootId)) {
                DynaBean dynaBeanItem = metaService.selectOne("JE_CORE_DICTIONARYITEM",
                        ConditionsWrapper.builder().eq("DICTIONARYITEM_DICTIONARY_ID",dictionary.getStr("JE_CORE_DICTIONARY_ID"))
                                .eq("SY_NODETYPE","ROOT"));
                rootId = dynaBeanItem.getStr("JE_CORE_DICTIONARYITEM_ID");
            }
        }
        wrapper.eq("SY_FLAG", "1");

        //获取树形信息
        DynaBean table = beanService.getResourceTable(tableName);
        if (table == null) {
            array.add(emptyRoot);
            return array;
        }

        //构建树形模版
        JSONTreeNode template = beanService.buildJSONTreeNodeTemplate((List<DynaBean>) table.get(BeanService.KEY_TABLE_COLUMNS));
        //普通字典国际化处理
        if (en) {
            template.setText("DICTIONARYITEM_ITEMNAME_EN");
        }

        //字典配置sql条件
        String ddWhereSql = dictionary.getStr("DICTIONARY_WHERESQL", "");
        String ddOrderSql = dictionary.getStr("DICTIONARY_ORDERSQL", "");

        // 添加字典配置sql
        if (StringUtil.isNotEmpty(ddWhereSql)) {
            //formatSqlParameter 替换Sql中的系统变量 非预处理赋值
            wrapper.apply(queryBuilder.formatSqlParameter(ddWhereSql));
        }

        //排序条件
        String orderSql = query.buildOrder();
        if (StringUtils.isNotBlank(orderSql)) {
            orderSql = " ORDER BY " + orderSql;
        } else if (StringUtils.isNotBlank(ddOrderSql)) {
            orderSql = ddOrderSql;
        }
        wrapper.getParameter().put("orderSql", orderSql);

        //查询数据
        List<JSONTreeNode> jsonTreeNodeList = loadAsyncTreeNodeList(ddType,product,rootId, tableName, template, wrapper, "1".equals(isRoot), false);
        //添加根节点数据
        if ("1".equals(isRoot)) {
            JSONTreeNode root = new JSONTreeNode();
            root.setId(rootId);
            jsonTreeNodeList.add(root);
        }

        for (JSONTreeNode node : jsonTreeNodeList) {
            if (node.getId().equals(rootId) && "1".equals(isRoot)) {
                node.setText(ddName);
                node.setParent("ROOT");
                node.setDisabled("1");
                if (StringUtil.isNotEmpty(nodeInfo)) {
                    node.setNodeInfo(nodeInfo);
                    node.setId(node.getId() + "_" + nodeInfo);
                }
            } else {
                if (StringUtil.isNotEmpty(nodeInfo)) {
                    node.setNodeInfo(nodeInfo);
                    node.setId(node.getId() + "_" + nodeInfo);
                    node.setParent(node.getParent() + "_" + nodeInfo);
                }
            }
            if ("JE_CORE_DICTIONARYITEM".equals(tableName)) {
                node.setBean(new HashMap<String, Object>());
            }
        }

        if (!"1".equals(isRoot)) {
            array.addAll(jsonTreeNodeList);
        }

        if (StringUtil.isNotEmpty(nodeInfo)) {
            rootId = rootId + "_" + nodeInfo;
        }

        //构建树形结构
        JSONTreeNode rootNode = buildJSONNewTree(jsonTreeNodeList, rootId);

        if (onlyItem) {
            array.addAll(rootNode.getChildren());
        } else {
            array.add(rootNode);
        }

        return array;
    }

    @Override
    public List<JSONTreeNode> loadSyncTree(JSONObject obj,String product, boolean en, boolean onlyItem) {
        //构建返回结果
        List<JSONTreeNode> array = new ArrayList<>();

        //根节点ID,默认为ROOT
        String rootId = obj.getString("rootId");
        if (StringUtil.isEmpty(rootId)) {
            rootId = ConstantVars.TREE_ROOT;
        }

        //字典编码
        String ddCode = obj.getString("ddCode");
        //字典名称，非必需字段
        String ddName = obj.getString("ddName");
        //字典标识，非必需字段 创建根节点对象ID使用,一次加载多个字典时使用
        String nodeInfo = obj.getString("nodeInfo");

        String moreRoot = "0";
        if (obj.containsKey("params")) {
            JSONObject varObj = obj.getJSONObject("params");
            if (varObj.containsKey("moreRoot")) {
                moreRoot = varObj.getString("moreRoot");
            }
        }

        //构建根节点
        JSONTreeNode emptyRoot = new JSONTreeNode();
        emptyRoot.setText(ddName);
        emptyRoot.setParent("ROOT");
        emptyRoot.setId("ROOT_" + nodeInfo);
        emptyRoot.setNodeInfo(nodeInfo);

        //查找字典主表记录
        DynaBean dictionary = dicInfoCache.getCacheValue(ddCode);
        if (dictionary == null) {
            dictionary = metaService.selectOne("JE_CORE_DICTIONARY", ConditionsWrapper.builder().eq("DICTIONARY_DDCODE", ddCode));
            if (dictionary == null) {
                throw new PlatformException("未找到数据字典：" + ddCode + "!", PlatformExceptionEnum.JE_CORE_DIC_UNKOWN_ERROR, new Object[]{ddCode});
            }
        }

        //字典类型
        String ddType = dictionary.getStr("DICTIONARY_DDTYPE");
        if (!DDType.DYNA_TREE.equals(ddType)) {
            throw new PlatformException("错误的字典类型：" + ddType + "!", PlatformExceptionEnum.JE_CORE_DIC_UNKOWN_ERROR, new Object[]{ddCode});
        }

        //字典对应表名或类名
        String tableName = dictionary.getStr("DICTIONARY_CLASSNAME");
        //字典配置sql
        String ddWhereSql = dictionary.getStr("DICTIONARY_WHERESQL", "");
        String ddOrderSql = dictionary.getStr("DICTIONARY_ORDERSQL", "");

        //前端sql条件转换
        Query query;
        if (StringUtils.isNotBlank(obj.getString("j_query"))) {
            query = Query.build(obj.getString("j_query"));
        } else {
            query = new Query();
        }

        if(needFilterByProduct.contains(ddCode)){
            commonService.buildProductQuery(query);
        }

        List<Condition> customQuery = (List<Condition>) obj.get("customQuery");
        query.addCustoms(JSONArray.toJSONString(customQuery));

        //排序条件
        String orderSql = "";
        if (!query.getOrder().isEmpty()) {
            orderSql = " ORDER BY " + query.buildOrder();
        } else if (StringUtils.isNotBlank(ddOrderSql)) {
            orderSql = ddOrderSql;
        }

        //如果是多根树
        if ("1".equalsIgnoreCase(moreRoot)) {
            //查询根节点
            ConditionsWrapper selectRoot = query.buildWrapper()
                    .eq("SY_NODETYPE", "ROOT")
                    .apply(StringUtil.isNotEmpty(ddWhereSql), queryBuilder.formatSqlParameter(ddWhereSql));
            //根节点
            List<DynaBean> select = metaService.select(tableName, selectRoot);
            if (select.size() == 1) {
                DynaBean rootBean = select.get(0);
                rootId = rootBean.getStr(metaBeanService.getPKeyFieldNamesByTableCode(tableName));
            }
        }

        //获取资源表信息
        DynaBean table = metaBeanService.getResourceTable(tableName);
        if (table == null) {
            array.add(emptyRoot);
            return array;
        }

        //资源表树形字段配置
        JSONTreeNode template = metaBeanService.buildJSONTreeNodeTemplate((List<DynaBean>) table.get(BeanService.KEY_TABLE_COLUMNS));

        //树形转换字典的 自定义业务bean字段设置
        if (!Strings.isNullOrEmpty(dictionary.getStr("DICTIONARY_YWZD_CODE"))) {
            String[] ywzdCodes = dictionary.getStr("DICTIONARY_YWZD_CODE").split(",");
            template.setOtherBeanFiled(Arrays.asList(ywzdCodes));
        }


        //构建查询条件
        ConditionsWrapper selectDic = query.buildWrapper();
        // 添加字典配置sql
        if (StringUtil.isNotEmpty(ddWhereSql)) {
            //formatSqlParameter 替换Sql中的系统变量 非预处理赋值
            selectDic.apply(queryBuilder.formatSqlParameter(ddWhereSql));
        }

        //获取Admin权限sql
        String queryTableCode = obj.getString("queryTableCode");
        if (StringUtils.isNotBlank(queryTableCode)) {
            String adminPermSql = getQuerySql(queryTableCode);
            if (StringUtils.isNotBlank(adminPermSql)) {
                final String sql = adminPermSql;
                selectDic.and(i -> i.apply(queryBuilder.trimSql(sql)));
            }
        }

        //排序条件
        selectDic.getParameter().put("orderSql", orderSql);
        List<JSONTreeNode> jsonTreeNodeList = loadTreeNodeList(ddType, product,rootId, tableName, template, selectDic);
        for (JSONTreeNode node : jsonTreeNodeList) {
            if (node.getId().equals(rootId)) {
                node.setText(ddName);
                node.setParent("ROOT");
                node.setDisabled("1");
                if (StringUtil.isNotEmpty(nodeInfo)) {
                    node.setNodeInfo(nodeInfo);
                    node.setId(node.getId() + "_" + nodeInfo);
                }
            } else {
                if (StringUtil.isNotEmpty(nodeInfo)) {
                    node.setNodeInfo(nodeInfo);
                    node.setId(node.getId() + "_" + nodeInfo);
                    node.setParent(node.getParent() + "_" + nodeInfo);
                }
            }
        }
        if (StringUtil.isNotEmpty(nodeInfo)) {
            rootId = rootId + "_" + nodeInfo;
        }

        JSONTreeNode rootNode = buildJSONNewTree(jsonTreeNodeList, rootId);
        if (onlyItem) {
            array.addAll(rootNode.getChildren());
        } else if (emptyRoot.getId().equals(rootNode.getId())) {
            array.add(rootNode);
        } else {
            rootNode.setParent("ROOT");
            try {
                rootNode.setText(rootNode.getBean().get(template.getText()).toString());
            } catch (Exception e) {
                logger.debug(e.getMessage());
            }
            rootNode.setDisabled("0");
            rootNode.setIcon("");
            emptyRoot.getChildren().add(rootNode);
            array.add(emptyRoot);
        }
        return array;
    }

    @Override
    public List<JSONTreeNode> loadLinkTree(String ddCode, String parentId, String parentCode, String rootId, String paramStr, boolean en, Query query) {
        throw new PlatformException("该字典类型不支持联动!", PlatformExceptionEnum.JE_CORE_DIC_UNKOWN_ERROR);
    }

}
